#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "rngs.h"
#include <math.h>

/*
 * Function to test adventurer card
 *
 *
 */
int* checkAdventurerEffect(struct gameState *post, int p, int randPos) {
  int * result = malloc(sizeof(int) * 3);
  struct gameState pre;
  memcpy (&pre, post, sizeof(struct gameState));

  int r, i; 

  //initialize result array
  for (i = 0; i < 3; i++){
    result[i] = 1;
  }

  //call cardEffect
  r = cardEffect (adventurer, 0, 0, 0, post, randPos, 0);

  //check that final 2 cards are treasure cards after cardEffect
  int treasureCount = 0;
  int lastCards = 2;
  for (i = 1; i <= lastCards; i++){
    int checkCard = post->hand[p][post->handCount[p] - i];
    if (checkCard == copper || checkCard == silver || checkCard == gold){
      treasureCount++;
    }
  }
  
  //check that only 2 total cards were retained in hand after cardEffect
  int checkDrawnCards = 0;
  int preCount = pre.handCount[p];
  int postCount = post->handCount[p];
  if (preCount + 2 == postCount){
    checkDrawnCards = 1;
  }

  //set results array
  int pass = 1;
  if (r != 0){
    result[0] = 0;
    pass = 0;
  }
  if (treasureCount != 2){
    result[1] = 0;
    pass = 0;
  }
  if (!(checkDrawnCards)){
    result[2] = 0;
    pass = 0;
  }

  //print detailed results
  if (pass == 0){
    printf("TEST FAILED\nGamestate:\n"
        "Player: %d\n"
        "starting deckCount: %d\n"
        "starting discardCount: %d\n"
        "starting handCount: %d\n"
        "ending deckCount %d\n"
        "ending discardCount %d\n"
        "ending handCount %d\n"                
        "Number of last 2 cards in hand that are treasure cards\n after playing adventurer card: %d\n"
        "Number of cards added to hand by playing adventurer card: %d\n", 
        p, pre.deckCount[p], pre.discardCount[p], pre.handCount[p], 
        post->deckCount[p], post->discardCount[p], post->handCount[p],
        treasureCount, (postCount - preCount));
  }
  
  return result;  
}

int main () {

  int i, j, n, p, randPos;

  //int k[10] = {adventurer, council_room, feast, gardens, mine,
	//       remodel, smithy, village, baron, great_hall};         

  //initialize test variables        
  int testCount = 0;
  int passCount = 0;
  int intcompleteTestCount = 0;
  int wrongTreasureCount = 0;
  int wrongDrawCount = 0;

  struct gameState G;
  
  printf ("Testing cardEffect for adventurer card.\n");

  printf ("RANDOM TESTS.\n\n");

  printf ("Any test failures will be detailed below.\n"
  "SUMMARY RESULTS APPEAR AT END OF REPORT\n\n");

  //initialize random generator
  SelectStream(2);
  PutSeed(3);
  
  //perform 8000 random tests
  for (n = 0; n < 8000; n++) {

    //fill gamestate with random values
    for (i = 0; i < sizeof(struct gameState); i++) {
      ((char*)&G)[i] = floor(Random() * 256);
    }
    
    //select a random player (0-3)
    p = floor(Random() * 4);
    assert(p != 4);
    
    //manually initialize game
    G.deckCount[p] = floor(Random() * (MAX_DECK + 1));
    G.discardCount[p] = floor(Random() * (MAX_DECK + 1));
    G.handCount[p] = floor(Random() * (MAX_HAND) + 1);
    G.whoseTurn = p;
    for (j = 0; j <G.deckCount[p]; j++){
      G.deck[p][j] = floor(Random() * treasure_map + 1);
    }
    for (j = 0; j <G.discardCount[p]; j++){
      G.discard[p][j] = floor(Random() * treasure_map + 1);
    }
    for (j = 0; j <G.handCount[p]; j++){
        G.hand[p][j] = floor(Random() * treasure_map + 1);
    }

    //make sure adventurer card is in hand
    randPos = floor(Random() * (G.handCount[p]));    
    G.hand[p][randPos] = adventurer;   

    //run test
    int * results = checkAdventurerEffect(&G, p, randPos);
    
    //parse results
    int resultsSize = 3;
    int pass = 1;
    int l;
    for (l = 0; l < resultsSize; l++){
      if (results[l] == 0){
        pass = 0;
        if(l == 0){
          intcompleteTestCount++;
        }
        else if (l == 1){
          wrongTreasureCount++;
        }
        else if (l == 2){
          wrongDrawCount++;
        }
      }
    }
    //track pass/fail
    if (pass == 1){
      passCount++;
    }
    else{
      printf("Test No. %d\n\n", testCount + 1);
    }
    testCount++;  
        
  }

  //print global results
  if (passCount == testCount){

    printf ("ALL TESTS OK\n");

  }
  else{

    printf("===============================================\n");

    printf("OVERALL RESULTS: %d TESTS PERFOMRED, %d TESTS PASSED\n\n", testCount, passCount);
    printf("Reasons for failures:\n1.  Test did not complete: %d test runs\n"
        "2.  Final 2 cards in player's hand not treasure cards: %d test runs\n"
        "3.  Player's handCount did not increase by 2 cards: %d test runs\n\n",
        intcompleteTestCount, wrongTreasureCount, wrongDrawCount);

  }
  
  return 0;
}

